#include <iostream>
#include "map.h"


using namespace std;


/**
 * Constructor
 *
 */
Map::Map()
{
	m_strName = "";
	m_strID = "";
}


/**
 * Destructor
 *
 */
Map::~Map()
{
}


/**
 * Set the size of map
 * @param unsigned int maxX - width of the map
 * @param unsigned int maxY - height of the map
 * @return void
 *
 */
void Map::setMapDimension(unsigned int maxX, unsigned int maxY)
{
	m_cells.resize(maxX, maxY);
}


/**
 * Copies the cell information at a specific location
 * @param unsigned int x - coordinate
 * @param unsigned int y - coordinate
 * @param MapCell cell - cell to copy
 * @return void
 *
 */
void Map::setCell(unsigned int x, unsigned int y, MapCell cell)
{
	if ((x < m_cells.numCols()) && 
		(y < m_cells.numRows()))
		m_cells(x, y) = cell;
}


/**
 * Set the Name of the Map
 * @param std::string name 
 * @return void
 *
 */
void Map::setName(std::string name)
{
	m_strName = name;
}


/**
 * Set Short name of the map
 * @param std::string id
 * @return void
 *
 */
void Map::setID(std::string id)
{
	m_strID = id;
}


/**
 * Set Short name of the map
 * @param std::string id
 * @return void
 *
 */
string Map::getName()
{
	return m_strName;
}


/**
 * Get Short name of the map
 * @param void
 * @return std::string
 *
 */
string Map::getID()
{
	return m_strID;
}


/**
 * Prints the whole map
 * @param void
 * @return void
 *
 */
void Map::print()
{
	cout << "@@@@@@@@@@@@@@@" << endl;
	cout << "Map name: " << m_strName << endl;
	cout << "ID: " << m_strID << endl;
	cout << "(X/Y) = (" << m_cells.numCols() << "/" << m_cells.numRows() << ")" << endl;

	for (unsigned int i = (m_cells.numRows() - 1); i >= 0; --i)
	{
		for (unsigned int j = 0; j < m_cells.numCols(); ++j)
		{
			if (m_cells(j, i).isActive())
			{
				cout << "[@]";
			}
			else
			{
				cout << "[ ]";
			}
		}
		cout << endl;
		if (i == 0)
			break;
	}
	cout << endl;
	cout << "@@@@@@@@@@@@@@@" << endl;
}


/**
 * Prints the whole map and place a 'P' at a specific location
 * @param unsigned int x - coordinate of player
 * @param unsigned int y - coordinate of player
 * @return void
 *
 */
void Map::print(unsigned int x, unsigned int y)
{
	cout << "@@@@@@@@@@@@@@@" << endl;
	cout << "Map name: " << m_strName << endl;
	cout << "ID: " << m_strID << endl;
	cout << "(X/Y) = (" << m_cells.numCols() << "/" << m_cells.numRows() << ")" << endl;

	for (unsigned int i = (m_cells.numRows() - 1); i >= 0; --i)
	{
		for (unsigned int j = 0; j < m_cells.numCols(); ++j)
		{
			if ((x == j) && (y == i))
			{
				cout << "[P]";
			}
			else
			{
				if (m_cells(j, i).isActive())
				{
					cout << "[ ]";
				}
				else
				{
					cout << "[X]";
				}
			}
		}
		cout << endl;
		if (i == 0)
			break;
	}
	cout << endl;
	cout << "@@@@@@@@@@@@@@@" << endl;
}


/**
 * linear search for a cell with a specific content
 * @param std::string searchStr - name of the content to search
 * @param t_coord& resultCoord - coordinate of the result
 * @return bool - true if a cell found
 *
 */
bool Map::findCell(std::string searchContent, t_coord& resultCoord)
{
	for (unsigned int i = 0; i < m_cells.numRows(); ++i)
	{
		for (unsigned int j = 0; j < m_cells.numCols(); ++j)
		{
			if (searchContent.compare(m_cells(j, i).getContent()) == 0)
			{
				resultCoord.x = j;
				resultCoord.y = i;
				return true;
			}
		}
	}
	return false;
}


/**
 * check the cell west of the coordinate given.
 * We check map boundaries and if cell is active.
 * @param t_coord coord - coordinate to check from
 * @return bool - true if it is fine to go there
 *
 */
bool Map::checkWest(t_coord coord)
{
	if ((coord.x > 0) && 
		(m_cells(coord.x - 1, coord.y).isActive()))
	{
		return true;
	}
	return false;
}


/**
 * check the cell east of the coordinate given.
 * We check map boundaries and if cell is active.
 * @param t_coord coord - coordinate to check from
 * @return bool - true if it is fine to go there
 *
 */
bool Map::checkEast(t_coord coord)
{
	if ((coord.x < (m_cells.numCols() - 1)) && 
		(m_cells(coord.x + 1, coord.y).isActive()))
	{
		return true;
	}
	return false;
}


/**
 * check the cell south of the coordinate given.
 * We check map boundaries and if cell is active.
 * @param t_coord coord - coordinate to check from
 * @return bool - true if it is fine to go there
 *
 */
bool Map::checkSouth(t_coord coord)
{
	if ((coord.y > 0) && 
		(m_cells(coord.x, coord.y - 1).isActive()))
	{
		return true;
	}
	return false;
}


/**
 * check the cell north of the coordinate given.
 * We check map boundaries and if cell is active.
 * @param t_coord coord - coordinate to check from
 * @return bool - true if it is fine to go there
 *
 */
bool Map::checkNorth(t_coord coord)
{
	if ((coord.y < (m_cells.numRows() - 1)) && 
		(m_cells(coord.x, coord.y + 1).isActive()))
	{
		return true;
	}
	return false;
}